/*+***********************************************************************************
 Filename: 9k_mcu01_mycore_v01\src\zh_peripheral_v01.v
 Description: a module to hold all kinds of peripherals.

 Modification:
   2022.11.07 Creation   H.Zheng (03_tinycore_step04\src\peripheral.v)
   2024.01.07 change addr to 12 bit width
   2024.02.08 add timer, add int_flag output port, clk_1MHz input port
              change peripheral unit address space to 16 
   2024.05.23 change button port to 3 bits for TangPrimer20kDock (A01_tinyriscv_mcu01\src\peripheral.v)
              timer module add ce_i port
   2024.05.24 add intctrl module. change int_flag to 1 bit.
              add uart0_rx_valid_int.
   2025.03.05 add clk_192MHz
   2025.08.17 rearrange to 9k_mcu01_mycore_v01 project
              remove clk_192MHz&clk_1MHz, remove int_flag & intctrl module
              re-allocate the peripheral memory map address,
              allow 64 registers each peripheral unit.
              add parameter 

Copyright (C) 2022-2025  Zheng Hui (hzheng@gzhu.edu.cn)

License: MulanPSL-2.0

***********************************************************************************-*/

/**
 * memory map of peripheral
 */
//total space: 0x10000000 - 0x1000ffff
//gpio:   0x10000000 - 0x100000ff
//uart0:  0x10000100 - 0x100001ff
//timer0: 0x10000200 - 0x100002ff

module zh_peripheral_v01 #(parameter CLK_FREQ_IN_MHz=27) (
  //from top
  input wire clk,
  input wire reset_n,
  input wire [2:0] button,
  output wire [5:0] led,
  input wire rxd,
  output wire txd,
  //from core
  input wire ce, //chip enable
  input wire wre, //write enable
  input wire [13:0] addr, //address bus, in words
  input wire [31:0] data_in,
  output wire [31:0] data_out
);

  //gpio
  //
  wire gpio_ce = (ce & (addr[13:6] == 8'h0)) ? 1'b1 : 1'b0;

  wire [31:0] gpio_data_out;
  zh_gpio_v01 m_gpio(
    .clk(clk),
    .reset_n(reset_n),
    .button(button),
    .led(led),
    .ce(gpio_ce),
    .wre(wre),
    .addr(addr[5:0]),
    .data_in(data_in),
    .data_out(gpio_data_out)

  );

  //uart
  //
  wire uart0_ce = (ce & (addr[13:6] == 8'h1)) ? 1'b1 : 1'b0;

  wire [31:0] uart0_data_out;

  zh_uart_v01 #(.CLK_FREQ_IN_MHz(CLK_FREQ_IN_MHz)) m_uart0(
    .clk(clk),
    .reset_n(reset_n),
    .rxd(rxd),
    .txd(txd),
    .ce(uart0_ce),
    .wre(wre),
    .addr(addr[5:0]),
    .data_in(data_in),
    .data_out(uart0_data_out)
  );

  //timer
  //
  wire timer0_ce = (ce & (addr[13:6] == 8'h2)) ? 1'b1 : 1'b0;
  wire [31:0] timer0_data_out;
  
  zh_timer_v01 m_timer0(
    .clk(clk),
    .reset_n(reset_n),
    .data_i(data_in),
    .addr_i(addr[5:0]),
    .we_i(timer0_ce & wre),
    .ce_i(timer0_ce),
    .data_o(timer0_data_out)
  );


  //data out mux
  assign data_out = (gpio_ce) ? gpio_data_out :
                    (uart0_ce) ? uart0_data_out :
                    (timer0_ce) ? timer0_data_out : 32'bz;


  
endmodule
